// This file contains everything specific to critical hits
var CB;
(function (CB) {
    var CriticalHits;
    (function (CriticalHits) {
        var cb = global.craig_brett;
        function handleCritical(e) {
            /// <summary>Handles effecters that have a critical hit chance</summary>
            var effecter = e.effecter;
            var skill = e.skill;
            var item = e.item;
            var effect = e.effect;
            var source = e.cur_unit;
            var target = e.target_unit;
            var targetTile = e.target_tile;
            var flags = effecter.ScriptFlags;
            if (unitIsCriticalHitImmune(target))
                return false;
            var chance = flags.get("critical_hit_chance");
            chance = addUnitCriticalHitModifiers(source, chance, "critical_hit_chance_mod");
            var defenceChance = target.ScriptFlags.get("critical_hit_defence_chance");
            defenceChance = addUnitCriticalHitModifiers(target, defenceChance, "critical_hit_defence_chance_mod");
            var isCritical = determineSuccess(chance, defenceChance);
            if (!isCritical)
                return isCritical; // not a critical hit, do normal damage logic
            say("Critical hit!");
            var pointString = "", criticalType = "";
            // if its an inflicting critical
            if (flags.get("critical_hit_inflict")) {
                pointString = flags.get("critical_hit_inflict");
                criticalType = "inflict";
            }
            else if (flags.get("critical_hit_restore")) {
                pointString = flags.get("critical_hit_restore");
                criticalType = "restore";
            }
            if (criticalType != "") {
                var pointHash = makeHashFromPointString(pointString);
                if (criticalType == "inflict")
                    source.DoDamageTo(target, pointHash, null);
                else if (criticalType == "restore")
                    source.DoRestoreTo(target, pointHash);
            }
            // if its got a critical effect
            var criticalEffect = flags.get("critical_hit_effect");
            if (criticalEffect) {
                shared.ApplyEffect(criticalEffect, target, target.Tile);
            }
            var msg = flags.get("critical_hit_message");
            if (msg) {
                msg = CB.chooseFromARandomSelectString(msg);
                say(msg.format(source.GetName(), target.GetName()));
            }
            // if we've done no restoring or inflicting, just an effect or something, return false as well so the game does damage logic
            return isCritical && criticalType != "";
        }
        CriticalHits.handleCritical = handleCritical;
        function determineSuccess(percentageChance, defenceChance) {
            if (defenceChance) {
                percentageChance -= defenceChance;
            }
            var random = Math.random().toFixed(2);
            if (random < percentageChance) {
                return true;
            }
            else {
                return false;
            }
        }
        function makeHashFromPointString(pointString) {
            var commaSplit = pointString.split(",");
            var hash = {};
            for (var index = 0; index < commaSplit.length; index++) {
                var pointValuePair = commaSplit[index];
                var barSplit = pointValuePair.split("|");
                var pointName = barSplit[0];
                var pointValue = barSplit[1];
                hash[pointName] = pointValue;
            }
            return hash;
        }
        function determineAmount(valueString) {
            if (valueString == "")
                return 0;
            return shared.Calculate(valueString);
        }
        function addUnitCriticalHitModifiers(unit, currentChance, flagName) {
            if (!currentChance)
                currentChance = 0;
            for (var index = 0; index < unit.Effects.length; index++) {
                var effect = unit.Effects[index];
                if (effect.ScriptFlags.get(flagName))
                    currentChance += effect.ScriptFlags.get(flagName);
            }
            var equippedItems = unit.GetEquippedItems();
            for (var index = 0; index < equippedItems.length; index++) {
                var item = equippedItems[index];
                if (item.ScriptFlags.get(flagName))
                    currentChance += item.ScriptFlags.get(flagName);
            }
            return currentChance;
        }
        function unitIsCriticalHitImmune(target) {
            if (Boolean(target.ScriptFlags.get("critical_hit_immune")) == true)
                return true;
            var effects = target.Effects;
            if (effects && effects.length > 0) {
                for (var i = 0; i < effects.length; i++) {
                    var effect = effects[i];
                    if (Boolean(effect.ScriptFlags.get("critical_hit_immune")) == true)
                        return true;
                }
            }
            var equipment = target.GetEquippedItems();
            if (equipment && equipment.length > 0) {
                for (var i = 0; i < equipment.length; i++) {
                    var item = equipment[i];
                    if (Boolean(item.ScriptFlags.get("critical_hit_immune")) == true)
                        return true;
                }
            }
            return false;
        }
    })(CriticalHits = CB.CriticalHits || (CB.CriticalHits = {}));
})(CB || (CB = {}));
